const util = require('util');
const debug = util.debuglog('oil-game:login:action');
const UserDO = require('../../../domain/userDO');
const httpRequest = require('request');
const time = require('../../../util/time');
const {
    Msg,
    Code,
    OIL_EXCHANGE_NUM,   //首页给客户端的N条石油交易记录
} = require('./consts');
const {
    Constant,   //邀请好友相关数据
} = require('../../mission/lib/consts');
const {
    updateContactInfo,    //设置用户联系方式
    getUserInfo,    //获取当前用户
} = require('./cache');
var random = require('string-random');
const {
    getUserByMongo,   //从Mogo中查询用户信息
    searchParentInfo,   // 查询父用户信息
    getUserByPhone,   //根据手机号获取用户
    saveNewUser,    //初始化保存用户数据
    saveUserByMySQL,    //初始化保存用户附加信息
    getUserMoneyAndOil,   //获取用户余额和石油
    getUserGradeLimit,    //获取用户等级限制
    getUserLevelInfo
} = require('./dao');
const {
    addApprentice,    // 有人邀请 更新父用户的徒弟 和 祖父用户的徒孙
    addDisciple,    // 更新新注册用户的师爷用户的数据
    getUpgradeData,   // 获取升级系统中首页需要的数据
    getWaitBoxNum,    // 获取待收取宝箱数量
    addInviteReward, //增加邀请人的日常任务奖励
    initUpgradeByMongo,//初始化升级信息数据表
    checkSignToday,   //今日是否已签到
    getLogOutCoins,   //获取离线金币
    getNowExchangeList,   //获取最近的N条石油交易记录
    getNowExchangeEssenceList,    // 返回最新的几条石油精华交易信息
    userWatchVideoTodayApi,
    getProductRpc, //在线用户每秒产金量
    isDoubleOpenRpc //是否开启双倍奖励
} = require('./api');
const {
    checkUserCode,    //从redis中验证查询验证码
    saveUserCode,   //存储手机验证码到redis中
    updatePhone,    //更新用户用于显示的联系信息
} = require('./cache');
const {default: BigNumber} = require('bignumber.js');
const {formatCoins} = require('../../upgrade/lib/action');

//查看注册是否合法
exports.checkRegisterLegal = async function (uid, phone, code) {
    debug("uid = %s  phone = %s  code = %s 查看注册是否合法", uid, phone, code);
    //手机号码验证
    if (!phone) throw new Error(Msg.REGISTER_PHONE_ERR);
    // 判断uid是否为空
    if (!uid) throw new Error(Msg.MISSING_PARAMETER);

    //从Mogo中查询用户信息，检测是否注册过
    if (await getUserByMongo(uid)) throw new Error(Msg.REGISTERED_ERR);
    //验证手机号是否注册过
    if (await getUserByPhone(phone)) throw new Error(Msg.PHONE_ALREADY_EXISTS_ERR);
    //验证手机验证码
    if (!await checkUserCode.call(this, uid, code)) throw new Error(Msg.REGISTER_CODE_ERR);
}

//用户注册时初始化相关的数据库表
exports.initUserDatabase = async function ({session, uid, union_id, nickname, avatar, gender, city, province, phone, ip}) {
    debug("uid = %s, union_id = %s, nickname = %s, avatar = %s, gender = %s, city = %s, province = %s, phone = %s, ip = %s " +
        "用户注册时初始化相关的数据库表", uid, union_id, nickname, avatar, gender, city, province, phone);
    //查询父用户ID和师爷ID
    let {parent_id, grandpa_id} = await getParentInfoByUnionId(union_id);
    //需要存储的用户数据
    let user = {uid, parent_id, union_id, nickname, avatar, gender, city, province, phone, ip};
    user.video_num = 0;
    user.invite_id = random(1, {numbers: false}) + random(5, {letters: false});
    user.gmt_create = new Date().getTime();
    user.gmt_modified = new Date().getTime();
    user.coins = '0';

    //初始化users，用户表
    await saveNewUser(user);
    //初始化用户附加信息到MySQL
    await saveUserByMySQL.call(this, uid);
    // 初始化升级信息数据表
    await initUpgradeByMongo.call(this, session, uid);

    // 更新父用户的徒弟
    if (parent_id) await addApprentice.call(this, session, parent_id);
    // 更新父用户的日常任务邀请徒弟的奖励次数
    //if (parent_id) await addInviteReward.call(this, session, parent_id);
    // 更新祖父用户的徒孙
    if (grandpa_id) await addDisciple.call(this, session, grandpa_id);
    return user;
}

//登陆后获取用户
exports.loginGetUser = async function (uid) {
    debug("uid = %s  登陆后获取用户信息", uid);
    // 判断uid是否为空
    if (!uid) throw new Error(Msg.MISSING_PARAMETER);
    //从Mongo中获取用户
    let user = await getUserByMongo(uid);
    // 用户未注册
    if (!user) {
        console.error('用户未注册 uid: + ' + uid);
        throw new Error(Msg.USER_NOT_REGISTER);
    }
    // 用户未绑定手机号
    if (!user.phone) throw new Error(Msg.PHONE_EMPTY_ERR);
    return user;
}

//客户登陆后初始化数据
exports.loginInitData = async function (session, user) {
    debug("user = %s  用户登陆后初始化数据", JSON.stringify(user));
    //设置用户监听
    let userInfo = await setUserEvent.call(this, session, user);
    this.app.loginService.setUser(userInfo);

    //整理客户端首页需要的数据
    return await indexPageData.call(this, session, userInfo);
}

//发送短信验证码
exports.sendPhoneCode = async function (uid, phone) {
    debug("用户 = %s  给手机 %s 开始发送验证码", uid, phone);
    //验证手机号是否合法
    if (!isPoneAvailable(phone)) {
        debug("给手机 %s 开始发送验证码失败，手机号格式不对", phone);
        throw new Error(Msg.PHONE_NOT_AVAILABLE);
    }
    //生成4位验证码
    let code = parseInt(Math.random() * 9000 + 1000, 10);
    debug("给手机 %s 发送验证码 %s ", phone, code);
    //存储手机验证码到redis中
    await saveUserCode.call(this, uid, code);
    //发送验证码给手机
    //await sendCodePost(phone, code);
    return code;
}

//修改用户联系方式
exports.updateContactInfo = async function (session, msg) {
    let {contactInfo} = msg;
    let {uid} = session;
    if (!contactInfo) {
        debug("uid = %s contactInfo = %s 修改联系方式失败, contactInfo为空", uid, contactInfo);
        return;
    }
    await updateContactInfo.call(this, uid, contactInfo);
}

//获取用户联系方式
exports.getContactInfo = async function (session, next) {
    let {uid} = session;
    let user = await getUserInfo.call(this, uid);
    return {contact_info: user.contact_info || ""};
}

//获取当前用户的等级
exports.getUsersGrade = async function (session) {
    let {uid} = session;
    //当前用户
    let user = this.app.loginService.getUser(uid);
    //未找到当前用户
    if (!user) return "";
    //当前用户徒子徒孙数
    let {apprentice_num, disciple_num} = user;
    //获取用户等级限制
    let userGradeLimit = await getUserGradeLimit.call(this, uid);

    //排序
    userGradeLimit = userGradeLimit.sort((item1, item2) => item2.apprentice - item1.apprentice);
    //计算当前等级
    let name = "";
    for (let i = 0; i < userGradeLimit.length; i++) {
        if (apprentice_num >= userGradeLimit[i].apprentice && disciple_num >= userGradeLimit[i].grandson) {
            name = userGradeLimit[i].name;
            break;
        }
    }
    return name;
}

/**
 * 给运营平台发送登陆通知
 * @param uid
 */
exports.sendManagerPlatform = function (uid) {
    httpRequest.post(
        'http://oil.njtrtw.ltd/api/logs/sign',
        {form: {'id': uid}},
        function (error, response, body) {
            if (!error && response.statusCode == 200) {
                console.error(body)
            }
        }
    );
}

//通过union_id获取父用户ID和父用户的parent_id
async function getParentInfoByUnionId(union_id) {
    //查询父用户信息
    let parentInfo = await searchParentInfo(union_id);
    //获取父用户
    let parentUser = parentInfo ? await getUserByMongo(parentInfo.parent_id) : null;
    //查询父用户ID
    let parent_id = parentUser ? parentUser.uid : 0;
    //查询师爷用户ID
    let grandpa_id = parentUser ? parentUser.parent_id : 0;
    return {parent_id, grandpa_id};
}

//整理客户端首页需要的数据
async function indexPageData(session, {
    uid, avatar, nickname, new_player_prize, last_login_time, last_logout_time,
    apprentice_num, disciple_num, invite_id, video_num, total_video, union_id, first_withdraw, real_open_id, welfare_oil,
    coins, double_time, begin_double, current_level
}) {
    //获取余额和石油
    let {money, total_money, oil, total_oil, essence_oil, total_essence_oil} = await getUserMoneyAndOil.call(this, uid);

    //获取当前待收取宝箱数量
    let {waitOpenBoxLen} = await getWaitBoxNum.call(this, session, uid);
    let today_sign = await checkSignToday.call(this, uid);

    //矿层信息
    let levelInfo = await getUserLevelInfo.call(this, uid);
    //获取离线金币
    let {logOutCoins, logOutInterval} = await getLogOutCoins.call(this, session, last_login_time, last_logout_time);

    //获取石油交易记录
    let latelyExchangeList = await getNowExchangeList.call(this, session, OIL_EXCHANGE_NUM);
    latelyExchangeList = latelyExchangeList ? latelyExchangeList.nowExchangeList : [];
    latelyExchangeList = latelyExchangeList.map(item => Object.assign({type: "oil"}, item));
    //获取精华石油交易记录
    let latelyExchangeEssenceListList = await getNowExchangeEssenceList.call(this, session, OIL_EXCHANGE_NUM);
    latelyExchangeEssenceListList = latelyExchangeEssenceListList ? latelyExchangeEssenceListList.nowExchangeList : [];
    latelyExchangeEssenceListList = latelyExchangeEssenceListList.map(item => Object.assign({type: "essence"}, item));
    //截取最近的10条记录
    latelyExchangeList = latelyExchangeList.concat(latelyExchangeEssenceListList);
    latelyExchangeList.sort((item1, item2) => new Date(item2.updated_at).valueOf() - new Date(item1.updated_at).valueOf());
    latelyExchangeList = latelyExchangeList.slice(0, OIL_EXCHANGE_NUM);

    //获取用户等级
    let title = await exports.getUsersGrade.call(this, session);

    //今天用户是否观看过视频，没有观看过，重置视频数量
    let ret = await userWatchVideoTodayApi.call(this, session, uid);
    if (!ret) {
        video_num = 0;
        welfare_oil = 0;
    }
    //双倍奖励是否开启
    double_time = await isDoubleOpenRpc.call(this, session, uid);
    //每秒产金量
    let product_per_sec = await getProductRpc.call(this, session, uid);

    return {
        uid,    //用户ID
        union_id,
        userId: invite_id ? invite_id : '000000',//客户端显示UID
        title,    //矿工名称
        avatar: avatar ? avatar : "",   //头像
        nickname: nickname ? nickname : "",   //昵称
        money: money ? money : 0,    //余额
        total_money: total_money ? total_money : 0, //金钱累积
        oil: oil ? oil : 0,    //石油
        total_oil: total_oil ? total_oil : 0, //石油累积
        new_player_prize: new_player_prize ? new_player_prize : 0,//领取新手奖励标记
        today_sign: today_sign ? today_sign : 0,//今天是否已签到
        apprentice_num: apprentice_num ? apprentice_num : 0,//徒孙数量
        disciple_num: disciple_num ? disciple_num : 0,//徒弟数量
        video_num: video_num,
        total_video: total_video,
        logOutCoins,    //离线金币数量
        logOutInterval,    //有效离线时长
        waitOpenBoxLen: waitOpenBoxLen ? waitOpenBoxLen : 0,   //待领取宝箱
        friendOilNum: Constant.OIL_INVITE_NUM,   //邀请好友给石油数
        latelyExchangeList,   //最新的N条石油记录
        first_withdraw: first_withdraw == null ? false : first_withdraw, //是否领取过激励奖金
        real_open_id: real_open_id, //用户的真实openid
        welfare_oil: welfare_oil, //每日福利奖励的石油
        essence_oil: essence_oil, //当前精华石油
        total_essence_oil: total_essence_oil, //累积精华石油
        coins: coins, //当前金币
        coins_format: formatCoins(BigNumber(coins)),//格式化后的金币字符串
        double_time: double_time, //是否开启双倍奖励
        begin_double: begin_double, //开启双倍时间
        levelInfo: levelInfo, //矿层信息
        current_level: current_level, //矿层等级
        product_per_sec: formatCoins(BigNumber(product_per_sec)) //每秒产金量
    };
}

//设置用户监听
async function setUserEvent(session, user) {
    let userInfo = new UserDO(user);
    userInfo.on('updateUser', () => {
        this.app.get('sync').flush('userSync.updateUser', userInfo.uid, userInfo.strip());
    });
    userInfo.on('updateMap', () => {
        this.app.get('sync').flush('userSync.updateMap', userInfo.uid, userInfo.strip());
    });
    userInfo.on('chestSave', () => {
        this.app.get('sync').flush('userSync.updateOpenChest', userInfo.uid, userInfo.strip());
    });
    userInfo.on('exchangeSave', () => {
        this.app.get('sync').flush('userSync.updateExchange', userInfo.uid, userInfo.strip());
    });
    userInfo.on('upgradeSave', () => {
        this.app.get('sync').flush('userSync.updateUpgrade', userInfo.uid, userInfo.strip());
    });
    userInfo.on('luckDrawSave', () => {
        this.app.get('sync').flush('userSync.luckDrawSave', userInfo.uid, userInfo.strip());
    });
    userInfo.on('syncBox', () => {
        this.app.get('sync').flush('userSync.syncBox', userInfo.uid, userInfo.strip());
    });
    userInfo.on('exchangeEssenceSave', () => {
        this.app.get('sync').flush('userSync.exchangeEssenceSave', userInfo.uid, userInfo.strip());
    });

    // 设置登陆时间
    userInfo.last_login_time = new Date().valueOf();
    // 设置ip
    userInfo.ip = session.get('ip');
    return userInfo;
}

//验证手机号是否合法
function isPoneAvailable(poneInput) {
    let myreg = /^[1][3,4,5,7,8,9,6,2][0-9]{9}$/;
    return myreg.test(poneInput);
}

//发送验证码
function sendCodePost(phone, code) {
    debug("给手机 %s 发送验证码 %s ", phone, code);
    httpRequest({
        url: 'http://oil.njtrtw.ltd/api/sms/send?phone=' + phone + '&code=' + code,
        method: "GET"
    }, function (error, response, body) {
        console.log('error')
        console.log(error)
        console.log('body')
        console.log(body)
        console.log('response')
        console.log(response)
        if (response && response.statusCode != 200) {
            console.error('sendCodePost 执行失败 response.statusCOde' + response.statusCode)
            console.error('sendCodePost 执行失败 error' + error)
            return;
        } else {
        }
    });
}
